<!--
 * @Description: 基础表格
 * @Author: chenju
 * @Date: 2022-01-13 16:16:24
 * @LastEditors: qingyang
 * @LastEditTime: 2023-07-24 18:12:51
-->
<template>
  <vxe-table
    ref="baseTableRef"
    class="c-base-table"
    :class="[
      props.border === true ? 'c-base-table--border' : '',
      props.cellHeightSize && props.cellHeightSize !== 'default'
        ? `c-base-table--cell-height__${props.cellHeightSize}`
        : ''
    ]"
    :column-config="{ resizable: true }"
    :row-config="getRowConfig"
    :border="props.border"
    size="medium"
    :data="props.useDataSource ? localDataSource : isFrontSearch ? filterData : dataSource"
    v-loading="loading"
    @checkbox-all="handleSelectionChange"
    @checkbox-change="handleSelectionChange"
    :sort-config="{
      remote: true,
      trigger: 'cell',
      orders: ['desc', 'asc', null]
    }"
    @sort-change="handleSortChange"
    @cell-dblclick="cellDblclick"
    v-bind="vxeTableNativeAttrs"
  >
    <template #empty>
      <slot name="empty">
        <div class="empty">
          <img class="img" src="@/assets/images/no-task.png" />
          <p class="g-font-14n3">暂无数据</p>
        </div>
      </slot>
    </template>
    <template #default>
      <vxe-column type="checkbox" width="50" fixed="left" v-if="props.selection"></vxe-column>
      <slot></slot>
      <template v-if="props.tableFieldsSetting?.length">
        <template v-for="item in props.tableFieldsSetting" :key="item.key">
          <vxe-column v-bind="getTableColumnProps(item)" v-if="isShowColumn(item)">
            <template #header="{ column, columnIndex }" v-if="item.headerSlot || item.titleTips">
              <slot
                :name="item.headerSlot"
                :column="column"
                :columnIndex="columnIndex"
                v-if="item.headerSlot"
              />
              <CTableColumnHeaderWithTitleTips :title="item.title" :titleTips="item.titleTips" />
            </template>
            <template #default="scope">
              <template v-if="item.slot">
                <slot :name="item.slot" :scope="scope"></slot>
              </template>
              <template v-else>
                {{ empty(scope.row[item.field as string]) }}
              </template>
            </template>
          </vxe-column>
        </template>
      </template>
    </template>
  </vxe-table>
  <Teleport :to="paginationTeleport" v-if="pagination && paginationTeleport && isRendered">
    <el-pagination
      class="c-pagination"
      size="normal"
      v-model:currentPage="currentPage"
      :page-sizes="paginationPageSizes"
      :page-size="pageSize"
      :pager-count="5"
      :layout="paginationLayout"
      :total="totalCount"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :prev-icon="CIconArrowLeft"
      :next-icon="CIconArrowRight"
    >
      <span v-if="paginationLayout.indexOf('slot') > -1">
        {{ totalPages ? currentPage : 0 }} / {{ totalPages }}</span
      >
    </el-pagination>
  </Teleport>
  <div class="c-table-footer g-flex-end-center" v-else-if="pagination && !paginationTeleport">
    <!-- <slot name="batchOperaBtns" :selection="multipleSelection"></slot> -->
    <el-pagination
      class="c-pagination"
      size="normal"
      v-model:currentPage="currentPage"
      :page-sizes="paginationPageSizes"
      :page-size="pageSize"
      :pager-count="7"
      :layout="paginationLayout"
      :total="totalCount"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :prev-icon="CIconArrowLeft"
      :next-icon="CIconArrowRight"
    >
    </el-pagination>
  </div>
  <FixedTableFooterBar
    :hasCollapse="props.hasCollapse"
    v-model:is-check-all="checkAll"
    v-model:is-indeterminate="isIndeterminate"
    :multiple-selection="multipleSelection"
    @toggle-check-all="handleCheckAllChange"
    v-if="isShowFooterBar && selection && multipleSelection?.length"
  >
    <slot name="batchOperaBtns" :selection="multipleSelection"></slot>
  </FixedTableFooterBar>
</template>

<script lang="ts">
export default {
  name: 'CTable'
};
</script>
<script lang="ts" setup>
import {
  defineProps,
  defineEmits,
  defineExpose,
  Ref,
  ref,
  computed,
  onMounted,
  onBeforeUnmount
} from 'vue';
import baseConfig from './config';
import { tableProps, TableFieldsSettingType } from './table';
import { VxeTablePropTypes } from '@xfchenju/vxe-table';
import FixedTableFooterBar from './fixed-table-footer-bar.vue';
import { debounce } from 'lodash';
import { empty } from '@/utils/index';
import CIconArrowLeft from '@/components/CIconArrowLeft/index.vue';
import CIconArrowRight from '@/components/CIconArrowRight/index.vue';
import CTableColumnHeaderWithTitleTips from './table-column-header.vue';

const props = defineProps(tableProps);
const emit = defineEmits(['sort-change', 'cell-dblclick', 'checkbox-change']);
const baseTableRef = ref();
const dataSource = ref<any[]>([]);
const originalSource = ref<any[]>([]);

const currentPage = ref(1);
const pageSize = ref(props.pagination?.pageSize || baseConfig.DEFAULT_PAGE_SIZE);
const paginationPageSizes = ref(props.pagination?.pageSizes || baseConfig.DEFAULT_PAGE_SIZES);
// NOTE 配置了slot就说明是自定义分页样式，自定义分页样式暂时固定为一种
const paginationLayout = ref(props.pagination?.layout || baseConfig.DEFAULT_PAGE_LAYOUT);
const paginationTeleport = ref(props.pagination?.teleport ?? false);
const totalCount = ref(0);
// 总页码
const totalPages = ref(0);
const loading = ref(false);

const vxeTableNativeAttrs = computed(() => {
  return {
    ...props.extraTableOption
  };
});

const getRowConfig = computed<VxeTablePropTypes.RowConfig>(() => {
  const rowConfig: VxeTablePropTypes.RowConfig = { isCurrent: true, isHover: true };
  if (props.rowKey) {
    rowConfig.useKey = true;
    rowConfig.keyField = props.rowKey;
  }
  return rowConfig;
});

// 表格加载方法
const getTableData = () => {
  // 加载数据
  if (props.loadData) {
    showLoading();
    const params = {
      current: currentPage.value,
      size: pageSize.value
    };
    const result = props.loadData(params);
    if (
      (typeof result === 'object' || typeof result === 'function') &&
      typeof result.then === 'function'
    ) {
      result
        .then((res: any) => {
          console.log('loadData res', res);
          dataSource.value = res.records || [];
          originalSource.value = res.records;
          totalCount.value = res.total || 0;
          totalPages.value = res?.pages || 0;
          hideLoading();
        })
        .catch((error: any) => {
          console.log('error', error);
          hideLoading();
        });
    } else {
      hideLoading();
    }
  }
};

// 每页条数改变
const handleSizeChange = (size: number) => {
  console.log('handleSizeChange', size);
  currentPage.value = 1;
  pageSize.value = size;
  refresh();
};
const cellDblclick = (row: any) => {
  emit('cell-dblclick', row);
};

// 当前页码改变
const handleCurrentChange = (page: number) => {
  console.log('handleCurrentChange', page);
  currentPage.value = page;
  refresh();
};

const checkAll = ref(false);
const isIndeterminate = ref(false);
// 选择框选项
const multipleSelection = ref<any[]>([]);
// 多选框
function handleSelectionChange({ checked }: any) {
  console.log('handleSelectionChange', checked);
  const $table = baseTableRef.value;
  if ($table) {
    const records = $table.getCheckboxRecords();
    multipleSelection.value = records;
  }
  if (
    multipleSelection.value?.length &&
    dataSource.value?.length &&
    dataSource.value.length === multipleSelection.value.length
  ) {
    // 全选
    checkAll.value = true;
    isIndeterminate.value = false;
  } else if (
    multipleSelection.value?.length &&
    dataSource.value?.length &&
    dataSource.value.length !== multipleSelection.value.length
  ) {
    // 半选
    checkAll.value = false;
    isIndeterminate.value = true;
  } else {
    // 未选
    checkAll.value = false;
    isIndeterminate.value = false;
  }
  emit('checkbox-change', $table);
}
// 全选
function handleCheckAllChange(val: boolean) {
  console.log('handleCheckAllChange', val);
  const $table = baseTableRef.value;
  if ($table) {
    if (val) {
      $table.setAllCheckboxRow(true);
      checkAll.value = true;
      isIndeterminate.value = false;
    } else {
      $table.setAllCheckboxRow(false);
      checkAll.value = false;
      isIndeterminate.value = false;
    }
    const records = $table.getCheckboxRecords();
    multipleSelection.value = records;
  }
}

/**
 * @Description: 刷新表格
 * @param {*} isReset 是否重置页码
 * @return {*}
 */
function refresh(isReset = false) {
  isReset && (currentPage.value = 1);
  // 清空勾选
  resetSelection();
  getTableData();
}

// 重置选择项
function resetSelection() {
  multipleSelection.value = [];
  baseTableRef.value?.clearCheckboxRow();
}

// 开关树的展开状态
function toggleRowExpansion(...options: any) {
  console.log('toggleRowExpansion', options);
  baseTableRef.value?.toggleRowExpansion(...options);
}

// 手动排序
function handleSortChange({ column, field, order, ...arg }: any) {
  console.log('handleSortChange table', column, field, order, arg);
  emit('sort-change', { column, field, order });
}

const localDataSource = computed(() => {
  return props.dataSource;
});

if (!props.useDataSource) {
  props.immediate && getTableData();
}

const isRendered = ref(false);
onMounted(() => {
  isRendered.value = true;
});

onBeforeUnmount(() => {
  isRendered.value = false;
});

const filterData = ref<any[]>([]);
const isFrontSearch = ref(false);
const searchEvent = debounce(
  (query: string, searchFields: string[], lazy?: boolean) =>
    searchEventCC(query, searchFields, lazy),
  400
);

function searchEventCC(query: string, searchFields: string[], lazy?: boolean) {
  const filterVal = String(query).trim().toLowerCase();
  if (lazy) {
    // 如果是本地懒加载列表搜索
    if (!query) {
      dataSource.value = originalSource.value;
      return;
    }
    let arr = originalSource.value.filter(item => {
      return searchFields.some(key => {
        return item[key] && item[key].trim().toLowerCase()?.includes(filterVal);
      });
    });
    arr.forEach(item => {
      item.filtered = true;
    });
    dataSource.value = arr;
    return;
  } else {
    refresh();
  }
  // const $table = baseTableRef.value;
  // if ($table) {
  //   const column = $table.getColumnByField(searchFields[0]);
  //   if (column) {
  //     // 修改第二个选项为勾选状态
  //     const option = column.filters[0];
  //     option.data = searchFields[1];
  //     if (filterVal || searchFields[1] === '1') {
  //       option.checked = true;
  //     } else {
  //       option.data = '';
  //       option.checked = false;
  //     }
  //     // 如果是直接修复筛选条件，则需要手动调用 updateData 处理表格数据
  //     $table.updateData();
  //   }
  // }
}

/**
 * 获取列的参数
 * @param item
 */
function getTableColumnProps(item: TableFieldsSettingType) {
  // console.log('getTableColumnProps', item);
  const { slot, headerSlot, ...params } = item;
  // NOTE 如果不设置overflow = false，默认增加
  if (params?.overflow !== false) {
    Object.assign(params, {
      'show-header-overflow': 'tooltip',
      'show-overflow': 'tooltip'
    });
  }
  return params;
}
/**
 * 是否显示列
 * @param item
 */
function isShowColumn(item: any) {
  // console.log('isShowColumn', item);
  const { columnSettingConfig, enabled } = item;
  if (enabled === false || !columnSettingConfig || columnSettingConfig?.enabled) return true;
  return false;
}

function operationTable(callback: (tableRef: Ref<any>) => void) {
  callback(baseTableRef);
}

function showLoading() {
  loading.value = true;
}

function hideLoading() {
  loading.value = false;
}

/**
 * 收起全部
 */
function clearTreeExpand() {
  baseTableRef.value?.clearTreeExpand();
}
defineExpose({
  // 需要暴露给其他页面
  clearTreeExpand,
  refresh,
  resetSelection,
  toggleRowExpansion,
  totalCount,
  multipleSelection,
  dataSource,
  searchEvent,
  baseTableRef,
  operationTable,
  showLoading,
  hideLoading
});
</script>
<style lang="scss">
@use '../styles/index.scss' as *;
</style>

<style lang="scss" scoped>
:deep(.el-table__empty-text) {
  line-height: 0;
}
.empty {
  padding: 45px 0 60px;
  img {
    width: 181px;
    height: 111px;
  }
}
</style>
